package com.alex.statistics.controller;


import com.alex.statistics.method.timeSeriesAnalysis.ExponentialSmoothingService;
import com.alex.statistics.method.timeSeriesAnalysis.LinearRegressionService;
import com.alex.statistics.method.timeSeriesAnalysis.MovingAverageService;
import com.alex.statistics.method.timeSeriesAnalysis.PolynomialFitService;
import com.alex.statistics.pojo.Result;
import com.alex.statistics.pojo.result.timeSeriesAnalysis.*;
import com.alex.statistics.pojo.request.timeSeriesAnalysis.*;
import com.alex.statistics.pojo.result.timeSeriesAnalysis.LinearRegressionResult;
import com.alex.statistics.pojo.result.timeSeriesAnalysis.PolynomialFitResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.DecimalFormat;
import java.util.List;

@RestController
@Tag(name = "时间序列分析")
@RequestMapping("/timeseries")
public class TimeSeriesAnalysisController {

    @Autowired
    private PolynomialFitService polynomialFitService;

    @Autowired
    private LinearRegressionService linearRegressionService;

    @Autowired
    private MovingAverageService movingAverageService;

    @Autowired
    private ExponentialSmoothingService exponentialSmoothingService;

    /**
     * 接口用于进行多项式拟合并返回拟合的系数
     *
     * @param request 请求模型，包含 x, y 数据和多项式的阶数
     * @return 拟合结果
     */
    @PostMapping("/polynomial-fit")
    @Operation(summary = "多项式拟合并返回拟合")
    public Result<PolynomialFitResult> polynomialFit(@RequestBody @Parameter(description = "多项式拟合请求参数") PolynomialFitRequest request) {
        List<Double> xData = request.getX();
        List<Double> yData = request.getY();
        int degree = request.getDegree();

        // 调用服务类进行拟合
        List<Double> coefficients = polynomialFitService.fitPolynomial(xData, yData, degree);
        DecimalFormat decimalFormat = new DecimalFormat("#.####");

        // 动态生成多项式公式，保留两位小数
        StringBuilder formula = new StringBuilder("y = ");
        for (int i = 0; i < coefficients.size(); i++) {
            double coefficient = coefficients.get(i);
            String formattedCoefficient = decimalFormat.format(coefficient);  // 保留两位小数
            if (i == 0) {
                formula.append(formattedCoefficient);
            } else {
                if (coefficient >= 0) {
                    formula.append(String.format(" + %s * x^%d", decimalFormat.format(coefficient), i));
                } else {
                    formula.append(String.format(" - %s * x^%d", decimalFormat.format(Math.abs(coefficient)), i));
                }
            }
        }

        // 创建返回对象
        PolynomialFitResult result = new PolynomialFitResult();
        result.setCoefficients(coefficients);
        result.setMessage("Polynomial fitting completed successfully.");
        result.setPredictionFormula(formula.toString());  // 动态生成的公式

        return Result.ok(result);
    }

    /**
     * 接口用于进行一元回归预测
     *
     * @param request 请求模型，包含 x 和 y 数据
     * @return 预测结果
     */
    @PostMapping("/linear-regression")
    @Operation(summary = "进行一元回归预测")
    public Result<LinearRegressionResult> linearRegression(@RequestBody @Parameter(description = "一元回归请求参数") LinearRegressionRequest request) {
        List<Double> xData = request.getX();
        List<Double> yData = request.getY();

        // 调用回归服务获取回归系数
        double[] coefficients = linearRegressionService.getCoefficients(xData, yData);

        // 返回回归系数及公式
        LinearRegressionResult result = new LinearRegressionResult();
        result.setCoefficients(coefficients);  // 斜率和截距

        // 动态生成预测公式
        double slope = coefficients[0];  // 斜率
        double intercept = coefficients[1];  // 截距
        String formula=null;
        if(intercept>=0)
            formula = String.format("y = %.2f*x + %.2f", slope, intercept);
        else  {
            formula=String.format("y = %.2f*x - %.2f", slope, Math.abs(intercept));
        }

        result.setPredictionFormula(formula);  // 设置动态公式

        return Result.ok(result);
    }
    /**
     * 接口用于进行移动平均预测
     *
     * @param request 请求模型，包含数据和窗口大小
     * @return 预测结果
     */
    @PostMapping("/moving-average")
    @Operation(summary = "进行移动平均数预测")
    public Result<MovingAverageResult> movingAverage(@RequestBody @Parameter(description = "移动平均数预测请求参数") MovingAverageRequest request) {
        int windowSize = request.getWindowSize();
        double[] data = request.getData();  // 获取数据

        // 调用服务进行移动平均计算
        double prediction = movingAverageService.predict(data, windowSize);

        // 返回窗口大小、计算公式和预测结果
        MovingAverageResult result = new MovingAverageResult();
        result.setWindowSize(windowSize);
        result.setPredictionFormula(String.format("y = (x1 + x2 + ... + xn) / %d", windowSize));


        return Result.ok(result);
    }
    /**
     * 接口用于进行指数平滑预测
     *
     * @param request 请求模型，包含数据和平滑系数
     * @return 预测结果
     */
    @PostMapping("/exponential-smoothing")
    @Operation(summary = "进行指数平滑预测")
    public Result<Double> exponentialSmoothing(@RequestBody @Parameter(description = "指数平滑预测请求参数") ExponentialSmoothingRequest request) {
        double alpha = request.getAlpha();
        // 返回平滑系数及公式
        double predict = exponentialSmoothingService.predict(request.getData(), alpha);
        return Result.ok(predict);
    }

}
